package com.carl.lambda.simpleLambda.lambda1;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class LambdaTest {

    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,99.99),
            new Employee("李四",28,999.99),
            new Employee("王五",32,9999.99),
            new Employee("赵六",48,9999.99),
            new Employee("钱七",58,9999.99)
    );

    //需求1:获取当前公司中员工大于35岁的员工信息
    public List<Employee> filterEmployees(List<Employee> list){
        List<Employee> employeeList = new ArrayList<>();
        for (Employee employee : list) {
              if (employee.getAge() >= 35){
                  employeeList.add(employee);
              }
        }
        return employeeList;
    }
    @Test
    public void Test(){
        for (Employee filterEmployee : filterEmployees(employees)) {
            System.out.println(filterEmployee);
        }
        System.out.println("-------------------------");
    }

    //需求变了2:获取当前公司中员工工资大于5000的员工信息
    public List<Employee> filterEmployees1(List<Employee> list){
        List<Employee> employeeList = new ArrayList<>();
        for (Employee employee : list) {
            if (employee.getSalary()>=5000){
                employeeList.add(employee);
            }
        }
        return employeeList;
    }
    /**
     * if (employee.getSalary()>=5000){employeeList.add(employee);}
     * if (employee.getAge() >= 35){employeeList.add(employee);}
     *  冗余代码太多
     *  优化方法1 策略模式优化:定义一个接口然后具体实现可以是按年龄过滤可以是按公司过滤
     *  接口名:MyPredicate
     *  然后定义具体的实现类 FilterEmployeeByAge
     */

    /**
     * 不同的过滤条件只需要写一遍这个方法就行
     * @param list
     * @param myPredicate
     * @return
     */
    public List<Employee> betterFilterEmployee(List<Employee> list,MyPredicate<Employee> myPredicate){
        ArrayList<Employee> employees = new ArrayList<>();
        for (Employee employee : list) {
            if (myPredicate.test(employee)){
                employees.add(employee);
            }
        }
        return employees;
    }
    @Test
    public void betterFilterAge(){
        List<Employee> employeeList = betterFilterEmployee(employees, new FilterEmployeeByAge());
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }

        System.out.println("-------------------------");
    }

    /**
     * 比如再实现一个工资大于5000的需求
     * 实现FilterEmployeeBySalary
     */
    @Test
    public void  betterFilterSalary(){
        List<Employee> employeeList = betterFilterEmployee(employees, new FilterEmployeeBySalary());
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }
        System.out.println("-------------------------");
    }

    /**
     * 优化方式二:匿名内部类
     * 匿名内部类的好处在于:
     * 不用定义FilterEmployeeByAge,FilterEmployeeBySalary具体的实现条件的类了
     */
    @Test
    public void filterByClass(){
        List<Employee> employeeList = betterFilterEmployee(employees, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getAge() >= 40;
            }
        });
        for (Employee employee : employeeList) {
            System.out.println(employee);
        }
        System.out.println("======================================================");
        List<Employee> employeeList1 = betterFilterEmployee(employees, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getName().equals("张三");
            }
        });
        for (Employee employee : employeeList1) {
            System.out.println(employee);
        }
    }

    /**
     * 优化方式三: lambda表达式
     */
    @Test
    public void betterFilter(){
        List<Employee> employeeList = betterFilterEmployee(employees, (e) -> e.getSalary() >= 5000);
        employeeList.forEach(System.out::println);
    }

    /**
     * 优化方式四 :Stream API
     */
    @Test
    public void bestFilter(){
        employees.stream()
                .filter((e) -> e.getSalary() >= 5000)
                .limit(2)
                .forEach(System.out::println);

        System.out.println("-----------------------------------------------");
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
    }



}
